﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ThreadSafeControls {
    public class ThreadSafeTreeNode {

        private readonly TreeNode _treeNode;
        private readonly ThreadSafeTreeView _treeView;
        private readonly ThreadSafeTreeNodeCollection _nodes;

        internal ThreadSafeTreeNode(TreeNode treeNode, ThreadSafeTreeView treeView) {
            if (treeNode == null)
                throw new ArgumentNullException("treeNode");
            else if (treeView == null)
                throw new ArgumentNullException("treeView");

            _treeNode = treeNode;
            _treeView = treeView;
            _nodes = new ThreadSafeTreeNodeCollection(_treeNode.Nodes, _treeView);
        }

        internal TreeNode TreeNode {
            get { return _treeNode; }
        }

        public ThreadSafeTreeView TreeView {
            get { return _treeView; }
        }

        public int Index {
            get { return _treeView.ReturnAsync(c => _treeNode.Index); }
        }

        public bool IsExpanded {
            get { return _treeView.ReturnAsync(c => _treeNode.IsExpanded); }
        }

        public bool IsVisible {
            get { return _treeView.ReturnAsync(c => _treeNode.IsVisible); }
        }

        public ThreadSafeTreeNode LastNode {
            get { return _treeView.ReturnAsync(c => _treeNode.LastNode).AsThreadSafe(_treeView); }
        }

        public string Name {
            get { return _treeView.ReturnAsync(c => _treeNode.Name); }
        }

        public ThreadSafeTreeNode NextNode {
            get { return _treeView.ReturnAsync(c => _treeNode.NextNode).AsThreadSafe(_treeView); }
        }

        public ThreadSafeTreeNode NextVisibleNode {
            get { return _treeView.ReturnAsync(c => _treeNode.NextVisibleNode).AsThreadSafe(_treeView); }
        }

        public ThreadSafeTreeNodeCollection Nodes {
            get { return _nodes; }
        }

        public ThreadSafeTreeNode Parent {
            get { return _treeView.ReturnAsync(c => _treeNode.Parent).AsThreadSafe(_treeView); }
        }

        public ThreadSafeTreeNode PrevNode {
            get { return _treeView.ReturnAsync(c => _treeNode.PrevNode).AsThreadSafe(_treeView); }
        }

        public ThreadSafeTreeNode PrevVisibleNode {
            get { return _treeView.ReturnAsync(c => _treeNode.PrevVisibleNode).AsThreadSafe(_treeView); }
        }

        public object Tag {
            get { return _treeView.ReturnAsync(c => _treeNode.Tag); }
            set { _treeView.UpdateAsync(c => _treeNode.Tag = value); }
        }

        public string Text {
            get { return _treeView.ReturnAsync(c => _treeNode.Text); }
            set { _treeView.UpdateAsync(c => _treeNode.Text = value); }
        }

        public void Collapse() {
            _treeView.UpdateAsync(c => _treeNode.Collapse());
        }

        public void Collapse(bool ignoreChildren) {
            _treeView.UpdateAsync(c => _treeNode.Collapse(ignoreChildren));
        }

        public void Expand() {
            _treeView.UpdateAsync(c => _treeNode.Expand());
        }

        public void ExpandAll() {
            _treeView.UpdateAsync(c => _treeNode.ExpandAll());
        }

        public int GetNodeCount(bool includeSubTrees) {
            return _treeView.ReturnAsync(c => _treeNode.GetNodeCount(includeSubTrees));
        }

        public void Remove() {
            _treeView.UpdateAsync(c => _treeNode.Remove());
        }

        public void Toggle() {
            _treeView.UpdateAsync(c => _treeNode.Toggle());
        }

        public static implicit operator ThreadSafeTreeNode(TreeNode node) {
            return node.AsThreadSafe(node.TreeView.AsThreadSafe());
        }

    }
}
